package cn.iocoder.yudao.module.system.util.neo4j;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.system.config.a_gaojian.ConnectionConfig;
import com.trs.hybase.client.TRSConnection;
import com.xingyuv.captcha.util.StringUtils;
import org.neo4j.driver.v1.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;

import static org.neo4j.driver.v1.Values.parameters;

public class KnowledgeGraphHandle {
    private static final String ckmurl = "http://192.168.8.190:8000/";

    public static String formatXML(String in) {

        if (StringUtils.isEmpty(in.trim())) {
            return "";
        }
        StringBuilder out = new StringBuilder();
        in = in.trim();
        int length = in.length();
        char[] ch;
        ch = new char[length + 1];
        ch = in.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            if (ch[i] != '\r' && ch[i] != '\t' && ch[i] != '\n') {
                out.append(ch[i]);
            }
        }
        return out.toString();
    }

    //chapter	章节名;incident	事件; relation	实体关系;bookUrl	图书地址;content	内容;
    public static void main(String[] args) {

        EntityRelationDO entityRelationDO = new EntityRelationDO();
        String bookUrl = "C:\\Users\\86187\\Desktop\\xml\\2_chapter_00001.xml";
        //String bookUrl = "C:\\Users\\86187\\Desktop\\xml\\2_chapter_00002.xml";
        try {
            String bookName = "xml";
            TRSConnection conn = ConnectionConfig.getTRSConnection();
            Driver driver = GraphDatabase.driver("bolt://192.168.8.184:7687", AuthTokens.basic("neo4j", "neo4j"));
            Session session = driver.session();
            StatementResult result = session.run("MATCH (n:" + bookName + ") WHERE n.name = $name " + "RETURN n.name as bookName", parameters("name", bookName));
            if (!result.hasNext()) {
                session.run("CREATE (n:" + bookName + " {bookName:'" + bookName + "',entity:'" + bookName + "'})");
            }
            // 创建一个DocumentBuilder对象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = null;
            builder = factory.newDocumentBuilder();
            // 通过parse()方法将XML文件加载到内存中形成DOM树
            Document document = builder.parse(bookUrl);
            // 获取根元素节点
            Element rootElement = document.getDocumentElement();
            // 遍历子元素节点
            NodeList sectList = rootElement.getElementsByTagName("sect1");
            NodeList nodeTitleList = rootElement.getElementsByTagName("title");
            NodeList nodeParaList = rootElement.getElementsByTagName("para");
            System.out.println("章节title======================" + nodeTitleList.item(0).getTextContent());
            System.out.println("章节简介para======================" + nodeParaList.item(0).getTextContent());
            entityRelationDO.setChapter(nodeTitleList.item(0).getTextContent());
            entityRelationDO.setIncident(nodeTitleList.item(0).getTextContent());
            entityRelationDO.setBookName(bookName);
            entityRelationDO.setRelationOrg(getOrgByRdf(session, nodeParaList.item(0).getTextContent(), bookName));
            entityRelationDO.setRelationPerson(getPersonByRdf(session, nodeParaList.item(0).getTextContent(), bookName));
            entityRelationDO.setBookUrl(bookUrl);
            entityRelationDO.setContent(nodeParaList.item(0).getTextContent());
            if (entityRelationDO.getRelationOrg().size() < 0 && entityRelationDO.getRelationPerson().size() < 0 && getOrgGraphByRdf(session, nodeParaList.item(0).getTextContent(), bookName).size() < 0) {
                entityRelationDO.setEntity(geEntity(nodeParaList.item(0).getTextContent()).toString());
            }

            for (int i = 0; i < sectList.getLength(); i++) {
                entityRelationDO = new EntityRelationDO();
                Node node = sectList.item(i);
                String title = "";
                String textContent = "";
                String[] list;
                if (node instanceof Element) {
                    Element element = (Element) node;
                    list = element.getTextContent().split("\n");
                    list = Arrays.copyOfRange(list, 1, list.length);
                    for (int j = 0; j < list.length; j++) {
                        if (StringUtils.isNotEmpty(list[j])) {
                            if (!Pattern.matches("\\d+", list[j])) {
                                if (j == 0) {
                                    title = list[j];
                                } else {
                                    textContent += list[j];
                                }
                            }
                        }
                    }
                    entityRelationDO.setChapter(nodeTitleList.item(0).getTextContent());
                    entityRelationDO.setIncident(title);
                    entityRelationDO.setBookName(bookName);
                    entityRelationDO.setRelationOrg(getOrgByRdf(session, textContent, bookName));
                    entityRelationDO.setRelationPerson(getPersonByRdf(session, textContent, bookName));
                    entityRelationDO.setBookUrl(bookUrl);
                    entityRelationDO.setContent(nodeParaList.item(0).getTextContent());
                    if (entityRelationDO.getRelationOrg().size() < 0 && entityRelationDO.getRelationPerson().size() < 0 && getOrgGraphByRdf(session, textContent, bookName).size() < 0) {
                        entityRelationDO.setEntity(geEntity(nodeParaList.item(0).getTextContent()).toString());
                    }
                    System.out.println("title======================" + title);
                    System.out.println("textContent======================" + textContent);
                }
            }



           /* // 获取根元素节点
            Element rootElement = document.getDocumentElement();
            NodeList nodeList = rootElement.getElementsByTagName("para");
            NodeList nodeTitleList = rootElement.getElementsByTagName("title");
            String str = "";
            for (int i = 0; i < nodeTitleList.getLength(); i++) {
                Node node = nodeTitleList.item(i);
                if (node instanceof Element) {
                    Element element = (Element) node;
                    str+=element.getTextContent();
                    System.out.println("str======================"+element.getTextContent());
                    //System.out.println("str======================"+str);
                    //String textContent = element.getTextContent();
                    //System.out.println("Text Content: " + textContent);
                    //geEntity(textContent);
                    //geRdf(textContent);
                    //System.out.println("===============================================");
                }
            }*/
            /*for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node instanceof Element) {
                    Element element = (Element) node;
                    str+=element.getTextContent();
                    System.out.println("str======================"+str);
                    //String textContent = element.getTextContent();
                    //System.out.println("Text Content: " + textContent);
                    //geEntity(textContent);
                    //geRdf(textContent);
                    //System.out.println("===============================================");
                }
            }*/
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (SAXException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 关系识别-人物关系识别（人物、机构、职务关系、国别信息）
     *
     * @return
     */
    public static JSONArray geEntity(String textContent) {
        String URL = ckmurl + "rs/ext/entity";
        HashMap<String, Object> paramMap = new HashMap<>();
        //正文
        paramMap.put("content", textContent);

        String result = HttpUtil.post(URL, paramMap);

        JSONObject resultJSONObject = JSONUtil.parseObj(result);
        JSONArray entityResultInfoJSONArray = resultJSONObject.getJSONArray("entityItemList");
        if (entityResultInfoJSONArray != null) {
            for (int i = 0; i < entityResultInfoJSONArray.size(); i++) {
                JSONObject obj = entityResultInfoJSONArray.getJSONObject(i);
                /*System.out.println(obj.get("person"));
                System.out.println(obj.get("country"));
                System.out.println(obj.get("org"));
                System.out.println(obj.get("career"));*/
                //包含国家、机构
                if (!obj.isNull("country") && !obj.isNull("org")) {
                    System.out.println(obj.get("country") + "============>包含<===========" + obj.get("org"));
                }
                //包含国家、机构
                if (!obj.isNull("person") && !obj.isNull("org") && !obj.isNull("career")) {
                    System.out.println(obj.get("person") + "============>" + obj.get("career") + "<===========" + obj.get("org"));
                }
            }
            return entityResultInfoJSONArray;
        }
        return null;
        //System.out.println(result.toString());
    }

    /**
     * 关系识别-人物属性关系识别（人物知识图谱抽取）
     *
     * @return
     */
    public static JSONArray getOrgGraphByRdf(Session session, String textContent, String bookName) {
        String URL = ckmurl + "rs/ext/rdf";
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("content", textContent);
        paramMap.put("model", "rdf_person");
        paramMap.put("segType", "2");

        String result = HttpUtil.post(URL, paramMap);
        JSONObject resultJSONObject = JSONUtil.parseObj(result);
        JSONArray rdfResultInfoJSONArray = resultJSONObject.getJSONArray("rdfResultInfo");
        for (int i = 0; i < rdfResultInfoJSONArray.size(); i++) {
            JSONObject obj = rdfResultInfoJSONArray.getJSONObject(i);
            if (StrUtil.isNotEmpty(obj.get("entity").toString()) && StrUtil.isNotEmpty(obj.get("relationship").toString()) && StrUtil.isNotEmpty(obj.get("feature").toString()) && StrUtil.isNotEmpty(obj.get("sen").toString()) && StrUtil.isNotEmpty(obj.get("entityType").toString())) {
                insertNeo4j(session, obj.get("entity").toString(), obj.get("feature").toString(), obj.get("relationship").toString(), obj.get("sen").toString(), obj.get("entityType").toString(), bookName);
            }
        }
        return rdfResultInfoJSONArray;
    }

    /**
     * 关系识别-人物属性关系识别（人物知识图谱抽取）
     *
     * @return
     */
    public static JSONArray getPersonByRdf(Session session, String textContent, String bookName) {
        String URL = ckmurl + "rs/ext/rdf";
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("content", textContent);
        paramMap.put("model", "rdf_person");
        paramMap.put("segType", "2");

        String result = HttpUtil.post(URL, paramMap);
        JSONObject resultJSONObject = JSONUtil.parseObj(result);
        JSONArray rdfResultInfoJSONArray = resultJSONObject.getJSONArray("rdfResultInfo");
        for (int i = 0; i < rdfResultInfoJSONArray.size(); i++) {
            JSONObject obj = rdfResultInfoJSONArray.getJSONObject(i);
            if (StrUtil.isNotEmpty(obj.get("entity").toString()) && StrUtil.isNotEmpty(obj.get("relationship").toString()) && StrUtil.isNotEmpty(obj.get("feature").toString()) && StrUtil.isNotEmpty(obj.get("sen").toString()) && StrUtil.isNotEmpty(obj.get("entityType").toString())) {
                if ("陈昌浩".equals(obj.get("entity").toString())) {
                    System.out.println(1);
                }
                insertNeo4j(session, obj.get("entity").toString(), obj.get("feature").toString(), obj.get("relationship").toString(), obj.get("sen").toString(), obj.get("entityType").toString(), bookName);
            }
        }
        return rdfResultInfoJSONArray;
    }

    public static JSONArray getOrgByRdf(Session session, String textContent, String bookName) {
        String URL = ckmurl + "rs/ext/rdf";
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("content", textContent);
        paramMap.put("model", "rdf_org");
        paramMap.put("segType", "2");

        String result = HttpUtil.post(URL, paramMap);
        JSONObject resultJSONObject = JSONUtil.parseObj(result);
        JSONArray rdfResultInfoJSONArray = resultJSONObject.getJSONArray("rdfResultInfo");
        for (int i = 0; i < rdfResultInfoJSONArray.size(); i++) {
            JSONObject obj = rdfResultInfoJSONArray.getJSONObject(i);
            if (StrUtil.isNotEmpty(obj.get("entity").toString()) && StrUtil.isNotEmpty(obj.get("relationship").toString()) && StrUtil.isNotEmpty(obj.get("feature").toString()) && StrUtil.isNotEmpty(obj.get("sen").toString()) && StrUtil.isNotEmpty(obj.get("entityType").toString())) {
                insertNeo4j(session, obj.get("entity").toString(), obj.get("feature").toString(), obj.get("relationship").toString(), obj.get("sen").toString(), obj.get("entityType").toString(), bookName);
            }
        }
        return rdfResultInfoJSONArray;
    }


    public static void geRdf(String textContent) {
        String URL = ckmurl + "rs/ext/rdf";
        HashMap<String, Object> paramMap = new HashMap<>();
        //正文
        paramMap.put("content", textContent);
        //模板名称
        paramMap.put("model", "rdf_person");
        //分词模式。
        //1-按句分词
        //2-按段分词
        //3-全文分词
        paramMap.put("segType", "2");

        String result = HttpUtil.post(URL, paramMap);
        JSONObject resultJSONObject = JSONUtil.parseObj(result);
        JSONArray rdfResultInfoJSONArray = resultJSONObject.getJSONArray("rdfResultInfo");
        for (int i = 0; i < rdfResultInfoJSONArray.size(); i++) {
            JSONObject obj = rdfResultInfoJSONArray.getJSONObject(i);
            /*System.out.println(obj.get("entity"));
            System.out.println(obj.get("relationship"));
            System.out.println(obj.get("feature"));*/
            if (StrUtil.isNotEmpty(obj.get("entity").toString()) && StrUtil.isNotEmpty(obj.get("relationship").toString()) && StrUtil.isNotEmpty(obj.get("feature").toString())) {
                System.out.println(obj.get("entity") + "============" + obj.get("relationship") + "===========" + obj.get("feature"));
            }
        }
        //System.out.println(result.toString());
    }

    /**
     * 关系识别-人物属性关系识别（人物知识图谱抽取）
     *
     * @return
     */
    public static void geRdfNew(String textContent) {
        String URL = ckmurl + "rs/ext/rdf-new";
        HashMap<String, Object> paramMap = new HashMap<>();
        //正文
        paramMap.put("content", textContent);
        //id
        //paramMap.put("id", "北京");
        //模板名称
        paramMap.put("model", "rdf_person");
        paramMap.put("model", "rdf_org");
        paramMap.put("model", "rdf_org_graph");
        //分词模式。
        //1-按句分词
        //2-按段分词
        //3-全文分词
        paramMap.put("segType", "1");
        String result = HttpUtil.post(URL, paramMap);
        System.out.println(result);
    }


    public static void insertNeo4j(Session session, String entity, String feature, String relationship, String sen, String entityType, String bookName) {
        Driver driver = GraphDatabase.driver("bolt://192.168.8.184:7687", AuthTokens.basic("neo4j", "neo4j"));
        Session session1 = driver.session();
        //session.run("CREATE (n:bookName {name:'书名'})");
        //String entity = "中央军委";
        //String feature = "1930年";
        //String relationship = "成立日期";
        //String sen = "从中央军委成立到1930年年底，中央军委所做的工作，就是使军委对红军的指挥权力逐步提高、扩大；发布了一系列关于红军指挥、统一红军编制、红军军政关系等指示。";
        //String entityType = "org";

        StatementResult result = session1.run("MATCH (n:" + bookName + ") WHERE n.entity = $entity " + "RETURN n.entity as entity", parameters("entity", entity));

        session1.run("CREATE (n:" + bookName + " {code:$code,entity: $entity,sen:$sen,entityType:$entityType,bookName:$bookName})",
                parameters("code", UUID.randomUUID().toString(), "entity", feature, "sen", sen, "entityType", entityType, "bookName", bookName));

        if (!result.hasNext()) {
            session1.run("CREATE (n:" + bookName + " {code:$code,entity: $entity,sen:$sen,entityType:$entityType,bookName:$bookName})",
                    parameters("code", UUID.randomUUID().toString(), "entity", entity, "sen", sen, "entityType", entityType, "bookName", bookName));
            if ("org".equals(entityType)) {
                session1.run("MATCH (b:" + bookName + "),(n:" + bookName + "),(m:" + bookName + ") WHERE b.entity='" + bookName + "' AND n.entity='" + entity + "' AND n.sen='" + sen + "' AND m.sen='" + sen + "' AND m.entity='" + feature + "'" +
                        " CREATE (b)-[:包含机构]->(n) CREATE (n)-[:" + relationship + "]->(m)");
            } else if ("person".equals(entityType)) {
                session1.run("MATCH (b:" + bookName + "),(n:" + bookName + "),(m:" + bookName + ") WHERE b.entity='" + bookName + "' AND n.entity='" + entity + "' AND n.sen='" + sen + "' AND m.sen='" + sen + "'  AND  m.entity='" + feature + "'" +
                        " CREATE (b)-[:包含人物]->(n) CREATE (n)-[:" + relationship + "]->(m)");
            }
        } else {
            session1.run("MATCH (n:" + bookName + "),(m:" + bookName + ") WHERE n.entity='" + entity + "' AND n.sen='" + sen + "' AND m.sen='" + sen + "'  AND  m.entity='" + feature + "' CREATE (n)-[:" + relationship + "]->(m)");
        }


        //session.close();
        //driver.close();
    }
}
